package net.begincode.bean;

import net.begincode.annotation.Config;
import net.begincode.annotation.ConfigValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import java.lang.reflect.Field;
import java.util.HashMap;

import static net.begincode.zookeeper.ZookeeperClient.getPathDataByKey;

/**
 * Created by saber on 2017/9/18.
 */
public class loadConfigBean  implements ApplicationListener<ContextRefreshedEvent> {

    private static Logger logger = LoggerFactory.getLogger(loadConfigBean.class);

    //反射类存储容器
    private static HashMap<String, Class> classMap = new HashMap<String, Class>();
    //反射对象存储容器
    private static HashMap<String, Object> objectMap = new HashMap<String, Object>();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        //避免双容器扫描重复加载
        //if(event.getApplicationContext().getParent() == null){
        logger.info("-------------------------------------->>> 加载容器bean开始");
        try {
            // 获取上下文
            ApplicationContext context = event.getApplicationContext();
            // 获取所有beanNames
            String[] beanNames = context.getBeanNamesForType(Object.class);
            for (String beanName : beanNames) {
                Config config = context.findAnnotationOnBean(beanName,Config.class);
                //判断该类是否含有Config注解,减少不必要的验证
                if (config != null) {
                    Class clazz = context.getBean(beanName).getClass();
                    Object object = context.getBean(beanName);
                    Field[] fields = clazz.getDeclaredFields();
                    for (Field field : fields){
                        if (field.isAnnotationPresent(ConfigValue.class)) {
                            String filedName = field.getName();
                            //存储映射关系
                            classMap.put(filedName, clazz);
                            objectMap.put(filedName, object);
                            //从zookeeper获取值
                            String value = getPathDataByKey(filedName, true);
                            //反射赋值
                            setFiled(field, value);
                        }
                    }
                }
            }
            logger.info("-------------------------------------->>> 加载容器bean结束");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 根据字段设置值
     * @param field
     * @param value
     */
    private static void setFiled(Field field, String value) {
        try {
            field.setAccessible(true);
            field.set(objectMap.get(field.getName()), value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据字段名设置值
     * @param fieldName
     * @param value
     */
    public static void setFiled(String fieldName, String value) {
        try {
            Class clazz = classMap.get(fieldName);
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(objectMap.get(field.getName()), value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


}
